// dotnet $DOTNET_CSC_DLL -nologo -t:library -r:"../../The Scroll of Taiwu_Data/Managed/System.dll" -r:"../../The Scroll of Taiwu_Data/Managed/netstandard.dll" -r:"../../The Scroll of Taiwu_Data/Managed/System.Reflection.Emit.ILGeneration.dll" -r:"../../The Scroll of Taiwu_Data/Managed/0Harmony.dll" -r:"../../The Scroll of Taiwu_Data/Managed/mscorlib.dll" -r:"../../The Scroll of Taiwu_Data/Managed/Assembly-CSharp.dll" -r:"../../The Scroll of Taiwu_Data/Managed/TaiwuModdingLib.dll" -r:"../../The Scroll of Taiwu_Data/Managed/Unity.TextMeshPro.dll" -r:"../../The Scroll of Taiwu_Data/Managed/UnityEngine.CoreModule.dll" -r:"../../The Scroll of Taiwu_Data/Managed/UnityEngine.UI.dll" -r:"../../The Scroll of Taiwu_Data/Managed/UnityEngine.dll" -optimize -deterministic -debug NeutronFrontend.cs *.CS -out:NeutronFrontend.dll
// -r:"../../The Scroll of Taiwu_Data/Managed/Mono.Cecil.dll" -r:"../../The Scroll of Taiwu_Data/Managed/System.Core.dll"   -r:"../../The Scroll of Taiwu_Data/Managed/System.Composition.AttributedModel.dll"
/**
 *  Neutron's Taiwu Collections
 *  Copyright (C) 2022 Neutron3529
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
#define FRONTEND

using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections.Generic;
using HarmonyLib;
using Utils;
[assembly: AssemblyVersion("0.0.0.3529")]
namespace ASmallCollectionsFromNeutron;
[TaiwuModdingLib.Core.Plugin.PluginConfig("ASmallCollectionsFromNeutron","Neutron3529","0.5.0")]
public class ASmallCollectionsFromNeutron : TaiwuModdingLib.Core.Plugin.TaiwuRemakePlugin {
    public override void Initialize()=>this.HarmonyInstance = new RobustHarmonyInstance(this.GetGuid());
    public override void Dispose()=>this.HarmonyInstance.UnpatchSelf();
    public static void logger(string s)=>GameData.Utilities.AdaptableLog.Info(s);
    public static void logwarn(string s)=>GameData.Utilities.AdaptableLog.Warning("<color=#FFFF00>"+s+"</color>",true);
    public RobustHarmonyInstance HarmonyInstance;
    public static bool dirty=false;
    public static int ciTangAdd=120;
    public static int mapSight=5;
    public static int favorStr=1;
    public static int N17=0;
    public static string InActiveGongFaColor="808080";

    public void buildingMaxLv(string key){
        //building_maxLv.Clear();
        string Additionals="";
        if(ModManager.GetSetting(this.ModIdStr, key, ref Additionals)){
            if(Additionals.Length>0) try {
                foreach (string gc in Additionals.Split(',')){
                    var tst=gc.Split('=');
                    sbyte count=(sbyte)int.Parse(tst[1].Trim());
                    short bonusType=-1;
                    if(Parser.Name2Id(tst[0],Config.BuildingBlock.Instance, ref bonusType))typeof(Config.BuildingBlockItem).GetField("MaxLevel",(BindingFlags)(-1)).SetValue(Config.BuildingBlock.Instance[bonusType],(sbyte)count);
                }
            } catch (Exception e){
                throw new Exception("建筑名称字符串（"+key+"）值有误，请修改字符串格式，或者将字符串置空\n请注意，这个错误的发生会导致部分建筑数据被修改，如果希望使用原版数据，需重启游戏。\n错误信息为：\n"+e.Message);
            }
        }
    }
    private bool enable(string key){
        try {
            return _enable(key);
        } catch(Exception ex){
            logwarn("enable 出错，出错键值为\""+key+"\"，错误原因是"+ex.Message);
            return false;
        }
    }
    private bool _enable(string key){
        bool enable=false;
        if(key=="N09S"){
            return ModManager.GetSetting(this.ModIdStr, key,ref ciTangAdd) && ciTangAdd!=0;
        } else if(key=="N14_2") {
            return ModManager.GetSetting(this.ModIdStr, key,ref mapSight) && mapSight>0;
        } else if(key=="N17") {
            return ModManager.GetSetting(this.ModIdStr, key,ref N17) && N17!=3;
        } else if(key=="N19") {
            return ModManager.GetSetting(this.ModIdStr, key,ref favorStr) && favorStr>0;
        } else if(key=="N23") {
            if(ModManager.GetSetting(this.ModIdStr, key,ref InActiveGongFaColor)){
                if(InActiveGongFaColor==null || InActiveGongFaColor.Length==6)InActiveGongFaColor="#808080";
                return InActiveGongFaColor.Length==7;
            }else{
                return false;
            }
        } else if(key=="N37") {
            buildingMaxLv(key);
        }
        return ModManager.GetSetting(this.ModIdStr, key,ref enable) && enable;
    }
    public override void OnModSettingUpdate(){
        this.HarmonyInstance.UnpatchSelf();
        if(enable("NForcePatch"))this.HarmonyInstance.PatchAll(typeof(Alive));
        if(enable("NForceOFF")){return;}
        if(enable("N00"))this.HarmonyInstance.PatchAll(typeof(RestrictionsMustDie));
        if(enable("N08"))this.HarmonyInstance.PatchAll(typeof(CatchAll));
        if(enable("N09"))this.HarmonyInstance.PatchAll(typeof(CiTang_NoAgeRestrict));
        if(enable("N09S"))this.HarmonyInstance.PatchAll(typeof(CiTang_BetterEffect_NoAuthCost));
        if(enable("N11_2"))this.HarmonyInstance.PatchAll(typeof(Speedup)); // display only
        if(enable("N14_2"))this.HarmonyInstance.PatchAll(typeof(RevealMap));
        if(enable("N15"))this.HarmonyInstance.PatchAll(typeof(TraitCost));
        if(enable("N17"))this.HarmonyInstance.PatchAll(typeof(RevealHealth));
        if(enable("N18"))this.HarmonyInstance.PatchAll(typeof(CricketAttackFirst));
        if(enable("N19"))this.HarmonyInstance.PatchAll(typeof(AppendFavor));
        if(enable("N20"))this.HarmonyInstance.PatchAll(typeof(AppendCharm));
        if(enable("N21"))this.HarmonyInstance.PatchAll(typeof(TransGenderGetCharm));
        if(enable("N22"))this.HarmonyInstance.PatchAll(typeof(FastSave));
        if(enable("N23"))this.HarmonyInstance.PatchAll(typeof(ShowCombat));
        if(enable("N24")){
            this.HarmonyInstance.PatchAll(typeof(BuildResource));
//            for(short i=0;i<Config.BuildingBlock.Instance.Count,i++){
//                Config.BuildingBlock.Instance[i].
//            }
        }
        if(enable("N26"))this.HarmonyInstance.PatchAll(typeof(AutoFast));
        if(enable("N32"))this.HarmonyInstance.PatchAll(typeof(UnlockShow));
//        if(enable("N33"))this.HarmonyInstance.PatchAll(typeof(Printing));
        if(enable("N34"))this.HarmonyInstance.PatchAll(typeof(FastCricketDeploy));
        if(enable("N35"))this.HarmonyInstance.PatchAll(typeof(Showququ));
        enable("N37");
        if(enable("N41"))this.HarmonyInstance.PatchAll(typeof(WorldMapModelGetFullBlockName));
        if(enable("N42"))this.HarmonyInstance.PatchAll(typeof(UI_ShopUnlock));
        if(enable("F0"))this.HarmonyInstance.PatchAll(typeof(UI_LegendaryBookOnNotifyGameData));
        if(enable("BF0-B"))this.HarmonyInstance.PatchAll(typeof(Master0));
        if(enable("BF1"))this.HarmonyInstance.PatchAll(typeof(MoveGrid));
    }
    [HarmonyPatch(typeof(UI_ModPanel),"OnModEntryRender")]
    public class Alive {
        public static void Postfix(UI_ModPanel __instance, int index, Refers refers, List<GameData.Domains.Mod.ModId> ____modIdList, InfinityScroll ____modsScroll){
            GameData.Domains.Mod.ModId modId = ____modIdList[index];
            GameData.Domains.Mod.ModInfo modInfo = ModManager.GetModInfo(modId);
            if(modInfo.Author=="Neutron3529" && modInfo.Title=="<color=#888800>平衡</color>与<color=#008888>不平衡</color>的模组集"){
                CToggle ctoggle = refers.CGet<CToggle>("IsModEnabledToggle");
                typeof(UnityEngine.UI.Toggle).GetField("m_IsOn",(BindingFlags)(-1)).SetValue((UnityEngine.UI.Toggle)ctoggle,true);
            }
        }
    }
    // [HarmonyPatch(typeof(ModManager),"LoadMod")]
    // public class Alive {
        // public static bool Prefix(GameData.Domains.Mod.ModInfo modInfo){
            // if(modInfo.Author=="Neutron3529"){
                // return false;
            // }
            // return true;
        // }

    public class BuildResource {
        [HarmonyPostfix, HarmonyPatch(typeof(UI_BuildingOverview), "CalcLegacyBuildingData")]
        public static void pfx(Dictionary<short,int> ____legaciesBuildingDict){
            if(____legaciesBuildingDict!=null){
                Config.BuildingBlock.Instance.Iterate(delegate(Config.BuildingBlockItem item){
                    if (item.Class == EBuildingBlockClass.BornResource ) {
                        ____legaciesBuildingDict[item.TemplateId]=255;
                    }
                    return true;
                });
            }
        }
        [HarmonyPostfix, HarmonyPatch(typeof(UI_BuildingOverview), "InitData")]
        public static void pfx(Dictionary<EBuildingBlockClass, List<Config.BuildingBlockItem>> ____buildingMap){
            Config.BuildingBlock.Instance.Iterate(delegate(Config.BuildingBlockItem item){
                if (item.Class == EBuildingBlockClass.BornResource ) {
                    // ____buildingMap[EBuildingBlockClass.Resource].Add(item);
                } else if (item.Class == EBuildingBlockClass.Function || item.Class == EBuildingBlockClass.Static /*// 超高概率红字*/) {
                    if(item!=null && item.Icon!=null && item.Icon.Length>1){
                        ____buildingMap[EBuildingBlockClass.Kungfu].Add(item);
                    }
                }
                return true;
            });
        }
        [HarmonyPostfix]
        [HarmonyPatch(typeof(UI_BuildingManage), "UpdateToggles")]
        public static void Postfix(CToggleGroup ____pageTogGroup,Config.BuildingBlockItem ____configData, bool ____isAtTaiwuVillage){
            ____pageTogGroup.Get(3).gameObject.SetActive(/* isBuilding &&  */____isAtTaiwuVillage);
            //this._pageTogGroup.Get(3).interactable = this._isBuildingManagementUnlocked && this._blockData.Level < this._configData.MaxLevel && (this._blockData.OperationType == 1 || this._blockData.OperationType == -1);
            ____pageTogGroup.Get(4).gameObject.SetActive(____configData.Class != EBuildingBlockClass.Static /* && this._configData.OperationTotalProgress[2] >= 0 */&& ____isAtTaiwuVillage);
        }
    }

    [HarmonyPatch(typeof(MouseTipLifeRecords), "RenderAllRecords")]// dead code
    public class FloatInformation{
        public static IEnumerable<CodeInstruction> Transpiler(MethodBase __originalMethod, IEnumerable<CodeInstruction> instructions) {
            instructions = new CodeMatcher(instructions)
                .MatchForward(false, // false = move at the start of the match, true = move at the end of the match
                    new CodeMatch(OpCodes.Callvirt,typeof(TMPro.TextMeshProUGUI).GetMethod("SetText", new Type[]{typeof(string),typeof(bool)}))
                ).Repeat( matcher => // Do the following for each match
                    matcher
                    .InsertAndAdvance(
                        new CodeInstruction(OpCodes.Ldarg_0),
                        new CodeInstruction(OpCodes.Ldfld,typeof(MouseTipLifeRecords).GetField("_charId",(BindingFlags)(-1))),
                        new CodeInstruction(OpCodes.Ldarg_0)
                    ).SetAndAdvance(
                        OpCodes.Call,typeof(FloatInformation).GetMethod("More")
                    ).InsertAndAdvance(
                        new CodeInstruction(OpCodes.Ret)
                    )
                ).InstructionEnumeration();
            return instructions;
        }
        public static void More(TMPro.TextMeshProUGUI desc, string content, bool T, int charId ,MouseTipLifeRecords instance){
            instance.AsynchMethodCall<int, int>(13, 2, charId, 5, delegate(int offset, GameData.Utilities.RawDataPool dataPool){
                desc.SetText(content, T);
                if (instance.Element != null) {
                    instance.Element.ShowAfterRefresh();
                }
            });
        }
    }
    [HarmonyPatch(typeof(MouseTipCombatSkill), "OnGetSkillDisplayData")]
    public class ShowCombat {
        public static MethodInfo UpdateSpecialEffectText=typeof(MouseTipCombatSkill).GetMethod("UpdateSpecialEffectText",(BindingFlags)(-1));
        public static MethodInfo GetSpecialEffectDesc=typeof(CommonUtils).GetMethod("GetSpecialEffectDesc",new Type[]{typeof(int), typeof(bool), typeof(bool)});
        public static void Prefix(MouseTipCombatSkill __instance, Config.CombatSkillItem ____configData){
            var dir=__instance.CGet<TMPro.TextMeshProUGUI>("DirectEffectDesc");
            var rev=__instance.CGet<TMPro.TextMeshProUGUI>("ReverseEffectDesc");
            if(dir!=null)UpdateSpecialEffectText.Invoke(__instance,new object[]{dir, "<color="+InActiveGongFaColor+">"+(string)(GetSpecialEffectDesc.Invoke(null, new object[]{(int)(____configData.TemplateId), true,false}))+"</color>"});
            if(rev!=null)UpdateSpecialEffectText.Invoke(__instance,new object[]{rev, "<color="+InActiveGongFaColor+">"+(string)(GetSpecialEffectDesc.Invoke(null, new object[]{(int)(____configData.TemplateId),false,false}))+"</color>"});
        }
        public static void Postfix(MouseTipCombatSkill __instance, Config.CombatSkillItem ____configData){
            if(!__instance.CGet<UnityEngine.GameObject>("SpecialEffect").activeSelf){
                __instance.CGet<UnityEngine.GameObject>("SpecialEffect").SetActive(true);
                var dir=__instance.CGet<TMPro.TextMeshProUGUI>("DirectEffectDesc");
                var rev=__instance.CGet<TMPro.TextMeshProUGUI>("ReverseEffectDesc");
                if(dir!=null)UpdateSpecialEffectText.Invoke(__instance,new object[]{dir, "<color="+InActiveGongFaColor+">"+(string)(GetSpecialEffectDesc.Invoke(null, new object[]{(int)(____configData.TemplateId), true,false}))+"</color>"});
                if(rev!=null)UpdateSpecialEffectText.Invoke(__instance,new object[]{rev, "<color="+InActiveGongFaColor+">"+(string)(GetSpecialEffectDesc.Invoke(null, new object[]{(int)(____configData.TemplateId),false,false}))+"</color>"});
            }
            __instance.CGet<UnityEngine.GameObject>("DirectEffectTitle").SetActive(true);
            __instance.CGet<UnityEngine.GameObject>("DirectDesc").SetActive(true);
            __instance.CGet<UnityEngine.GameObject>("ReverseEffectTitle").SetActive(true);
            __instance.CGet<UnityEngine.GameObject>("ReverseDesc").SetActive(true);
        }
    }
    [HarmonyPatch(typeof(UI_Bottom), "DoAdvance")]
    public class FastSave {
        public static void Postfix(){
            if(SingletonObject.getInstance<TimeManager>().GetLeftDaysInCurrMonth() > 0){
                DialogCmd dialogCmd4 = new DialogCmd
                {
                    Title = "快速存档",
                    Content = "即将使用GM面板的快速存档功能，是否确认？",
                    Type = 1,
                    Yes = GMFunc.Save
                };
                UIElement.Dialog.SetOnInitArgs(FrameWork.EasyPool.Get<FrameWork.ArgumentBox>().SetObject("Cmd", dialogCmd4));
                UIManager.Instance.ShowUI(UIElement.Dialog);
            }
        }
    }
    [HarmonyPatch(typeof(AvatarAdjustController),"SetTransGender")]
    public class TransGenderGetCharm {
        public static void Postfix(AvatarAdjustController __instance, short ____age){
            //var ct=__instance.AvatarData.GetCharm(____age,__instance.AvatarData.ClothDisplayId).ToString();
            var cx=__instance.AvatarData.CalCharmRate().ToString();
            var c0=__instance.AvatarData.GetBaseCharm().ToString();
            var c1=__instance.AvatarData.GetEyebrowsCharm().ToString();
            var c2=__instance.AvatarData.GetEyesCharm().ToString();
            var c3=__instance.AvatarData.GetNoseCharm().ToString();
            var c4=__instance.AvatarData.GetMouthCharm().ToString();
            var c5=__instance.AvatarData.GetFeatureCharm().Item1.ToString();
            var f0=__instance.AvatarData.Feature1Id.ToString();
            var f1=__instance.AvatarData.Beard1Id.ToString();
            var f2=__instance.AvatarData.Beard2Id.ToString();
            var f3=__instance.AvatarData.Wrinkle1Id.ToString();
            var f4=__instance.AvatarData.Wrinkle2Id.ToString();
            var f5=__instance.AvatarData.Wrinkle3Id.ToString();
            var m0=__instance.AvatarData.MouthId.ToString();
            var m1=__instance.AvatarData.MouthHeightPercent.ToString();
            var n0=__instance.AvatarData.NoseId.ToString();
            var n1=__instance.AvatarData.NoseHeightPercent.ToString();
            var e0=__instance.AvatarData.EyebrowId.ToString();
            var e1=__instance.AvatarData.EyebrowHeight.ToString();
            var e2=__instance.AvatarData.EyebrowAngle.ToString();
            var e3=__instance.AvatarData.EyebrowDistancePercent.ToString();
            var e4=__instance.AvatarData.EyesMainId.ToString();
            var e5=__instance.AvatarData.EyesHeightPercent.ToString();
            var e6=__instance.AvatarData.EyesAngle.ToString();
            var e7=__instance.AvatarData.EyesDistancePercent.ToString();
            var bd=__instance.AvatarData.AvatarId;
            DialogCmd dialogCmd4 = new DialogCmd
            {
                Title = "魅力展示",
                Content = ("\n\n\n\n\n\n当前人物体形id为"+bd+"，魅力如下：\n  <color=#AttractionType_Godlike>    基础魅力："+c0+"\n        眉毛魅力："+c1+"\n        眼睛魅力："+c2+"\n        鼻子魅力："+c3+"\n        嘴巴魅力："+c4+"\n        特征魅力："+c5+"\n    魅力比率："+cx+"\n      特征，胡须与皱纹："+f0+" "+f1+" "+f2+" "+f3+" "+f4+" "+f5+"\n      嘴与id和比例:"+m0+" "+m1+"\n      鼻子的:"+n0+" "+n1+"\n      眉毛id，高度，角度，间距"+e0+" "+e1+" "+e2+" "+e3+"\n      眼睛id，高度，角度，间距"+e4+" "+e5+" "+e6+" "+e7+"\n</color>").ColorReplace(),
                Type = 1,
                Yes = delegate(){}
            };
            UIElement.Dialog.SetOnInitArgs(FrameWork.EasyPool.Get<FrameWork.ArgumentBox>().SetObject("Cmd", dialogCmd4));
            UIManager.Instance.ShowUI(UIElement.Dialog);
        }
    }
    [HarmonyPatch(typeof(CommonUtils),"GetFavorString")]
    public class AppendFavor {
        public static string Postfix(string result, short favorability){
            if(favorability == short.MinValue)return result;
            string res;
            if(favorability<=0){res="\n<size=85%><color=#FavorabilityType_Hateful6>";} else {res="\n<size=85%><color=#FavorabilityType_Favorite6>";}
            if(favorStr==2)return "<size=85%>"+result+(res+(favorability/3).ToString("D4")+"</color></size>").ColorReplace();
            int favorabi;
            if(favorability<=-26000){favorabi=-(26000+favorability)*5/2;}
            else if(favorability<=-22000){favorabi=-(22000+favorability)*5/2;}
            else if(favorability<=-18000){favorabi=-(18000+favorability)*5/2;}
            else if(favorability<=-14000){favorabi=-(14000+favorability)*5/2;}
            else if(favorability<=-10000){favorabi=-(10000+favorability)*5/2;}
            else if(favorability<=-6000){favorabi=-(6000+favorability)*5/2;}
            else if(favorability<=-2000){favorabi=-(2000+favorability)*5/2;}
            else if(favorability<=2000){favorabi=(2000+favorability)*5/2;res="\n<size=85%><color=#FavorabilityType_Unfamiliar>";}
            else if(favorability<6000){favorabi=(favorability-2000)*5/2;}
            else if(favorability<10000){favorabi=(favorability-6000)*5/2;}
            else if(favorability<14000){favorabi=(favorability-10000)*5/2;}
            else if(favorability<18000){favorabi=(favorability-14000)*5/2;}
            else if(favorability<22000){favorabi=(favorability-18000)*5/2;}
            else if(favorability<26000){favorabi=(favorability-22000)*5/2;}
            else {favorabi=(favorability-26000)*5/2;}
            return result+(res+favorabi.ToString("D4")+"</color></size>").ColorReplace();
        }
    }
    [HarmonyDebug]
    [HarmonyPatch(typeof(CommonUtils),"GetCharmLevelText")]
    public class AppendCharm {
        public static string Postfix(string result, short charm){
            return result.Replace("</color>","\n"+charm+"</color>");
        }
    }
    [HarmonyPatch(typeof(UI_NewGame),"OnOverallDifficultyChange")]
    public class RestrictionsMustDie {
        public static void Prefix(UI_NewGame __instance){
            Refers refers = __instance.CGet<Refers>("SettingView");
            CToggleGroup ctoggleGroup = refers.CGet<CToggleGroup>("SetDifficultyHolder");
            refers.CGet<CToggleGroup>("SetValueHolder2").Get(3).interactable = true;
        }
    }
    // [HarmonyPatch(typeof(UI_BuildingTaiwuShrine),"InitTaiwuAvatar")]
    public class CiTang_NoAgeRestrict {
        [HarmonyPatch(typeof(UI_BuildingTaiwuShrine),"OnNotifyGameData")]
        static void Postfix(ref short ____taiwuAge){
            ____taiwuAge=100;
        }
        // static IEnumerable<MethodBase> TargetMethods(){
        //     int patch=0;
        //     foreach(var method in new string[]{"InitTaiwuInfo","InitTaiwuAvatar"})if(typeof(UI_BuildingTaiwuShrine).GetMethod(method,(BindingFlags)(-1)) != null){
        //         logger("即将patch:"+typeof(UI_BuildingTaiwuShrine).GetMethod(method,(BindingFlags)(-1)));
        //         yield return typeof(UI_BuildingTaiwuShrine).GetMethod(method,(BindingFlags)(-1));
        //         patch+=1;
        //     }
        //     logger($"祠堂年龄限制-共修改{patch}个函数");
        // }
        // public static IEnumerable<CodeInstruction> Transpiler(MethodBase __originalMethod, IEnumerable<CodeInstruction> instructions) {
        //     instructions = new CodeMatcher(instructions)
        //         .MatchForward(false, // false = move at the start of the match, true = move at the end of the match
        //             new CodeMatch(i=>i.opcode==OpCodes.Ldfld && (((FieldInfo)(i.operand)).Name=="CurrAge" || ((FieldInfo)(i.operand)).Name=="PhysiologicalAge"))
        //         ).Repeat( matcher => // Do the following for each match
        //             matcher
        //             .SetAndAdvance(
        //                 OpCodes.Pop,null
        //             ).InsertAndAdvance(
        //                 new CodeInstruction(OpCodes.Ldc_I4_S,100)
        //             )
        //         ).InstructionEnumeration();
        //     return instructions;
        // }
    }
    [HarmonyPatch(typeof(UI_BuildingTaiwuShrine),"OnSelectSkill")]
    public class CiTang_BetterEffect_NoAuthCost {
        public static IEnumerable<CodeInstruction> Transpiler(MethodBase __originalMethod, IEnumerable<CodeInstruction> instructions) {
            instructions = new CodeMatcher(instructions)
                .MatchForward(false, // false = move at the start of the match, true = move at the end of the match
                    new CodeMatch(OpCodes.Conv_I1),
                    new CodeMatch(OpCodes.Ldarg_2),
                    new CodeMatch(OpCodes.Call,typeof(GameData.Domains.Character.SkillQualificationBonus).GetConstructor(new Type[]{typeof(sbyte),typeof(sbyte),typeof(sbyte),typeof(short)}))
                ).Repeat( matcher => // Do the following for each match
                    matcher
                    .SetAndAdvance(
                        OpCodes.Pop,null
                    ).InsertAndAdvance(
                        new CodeInstruction(OpCodes.Ldc_I4_S,ciTangAdd)
                    ).Advance(3)
                ).InstructionEnumeration();
            return instructions;
        }
        //public static void Prefix(ref ushort ____shrineBuyTimes){
        //    ____shrineBuyTimes=65535;
        //}
        public static void Postfix(ref ushort ____shrineBuyTimes){
            ____shrineBuyTimes=0;
        }
    }
    [HarmonyPatch(typeof(WorldMapModel),"GetNeighborList")]
    public class RevealMap {
        public static void Prefix(ref int maxSteps){
            maxSteps=Math.Max(maxSteps,mapSight);
        }
    }
    [HarmonyPatch(typeof(UI_CricketCombat),"OnListenerIdReady")]
    public static class CricketAttackFirst {
        public static IEnumerable<CodeInstruction> Transpiler(MethodBase __originalMethod, IEnumerable<CodeInstruction> instructions) {
            instructions = new CodeMatcher(instructions)
                .MatchForward(false, // false = move at the start of the match, true = move at the end of the match
                    new CodeMatch(OpCodes.Ldc_I4_S,50),
                    new CodeMatch(OpCodes.Ldc_I4_S,100)
                ).Repeat( matcher => // Do the following for each match
                    matcher
                    .SetAndAdvance(
                        OpCodes.Ldc_I4_S,100
                    ).Advance(1)
                ).InstructionEnumeration();
            return instructions;
        }
    }
    [HarmonyPatch(typeof(UI_CatchCricket),"OnClickCatchPlace")]
    public static class CatchAll {
        //public static UI_CatchCricket.CricketPlaceInfo[] catchPlaceList=new UI_CatchCricket.CricketPlaceInfo[21];
        //public static void Prefix(UI_CatchCricket.CricketPlaceInfo[] ____catchPlaceList){catchPlaceList=____catchPlaceList;}
        public static IEnumerable<CodeInstruction> Transpiler(MethodBase __originalMethod, IEnumerable<CodeInstruction> instructions) {
            foreach(CodeInstruction i in instructions){
                if(i.opcode==OpCodes.Call && ((MethodInfo)(i.operand)).Name.Contains("AddMethodCall") ){
                    i.operand=typeof(CatchAll).GetMethod("catch_all");
                }
                yield return i;
            }
        }
        public static void catch_all(int listenerId, ushort domainId, ushort methodId, short arg1, short arg2, short arg3, sbyte arg4) {
        //    foreach(var place in catchPlaceList){
        //        GameData.GameDataBridge.GameDataBridge.AddMethodCall<short, short, short, sbyte>(listenerId, domainId, methodId, place.CricketColorId, place.CricketPartsId, 100, place.PlaceId);
                //GameData.GameDataBridge.GameDataBridge.AddMethodCall<short, short, short, sbyte>(listenerId, domainId, methodId, 18, 0, 100, arg4);// 天蓝青
                //GameData.GameDataBridge.GameDataBridge.AddMethodCall<short, short, short, sbyte>(listenerId, domainId, methodId, 19, 0, 100, arg4);// 三段锦
                //GameData.GameDataBridge.GameDataBridge.AddMethodCall<short, short, short, sbyte>(listenerId, domainId, methodId, 21, 0, 100, arg4);// 八败
                GameData.GameDataBridge.GameDataBridge.AddMethodCall<short, short, short, sbyte>(listenerId, domainId, methodId, arg1, arg2, 100, arg4);//应该捉到的蛐蛐，将声量放大到100以保证捕捉效果
                GameData.GameDataBridge.GameDataBridge.AddMethodCall<short, short, short, sbyte>(listenerId, domainId, methodId, 21, 19, 100, arg4);// 八败三段锦
                GameData.GameDataBridge.GameDataBridge.AddMethodCall<short, short, short, sbyte>(listenerId, domainId, methodId, 21, 19, 100, arg4);// 八败三段锦
                GameData.GameDataBridge.GameDataBridge.AddMethodCall<short, short, short, sbyte>(listenerId, domainId, methodId, 21, 19, 100, arg4);// 八败三段锦
        //    }
        }
    }
    [HarmonyPatch(typeof(UI_Make),"CheckMakeCondition")]
    public class Speedup{
        public static IEnumerable<CodeInstruction> Transpiler(MethodBase __originalMethod, IEnumerable<CodeInstruction> instructions) {
            instructions = new CodeMatcher(instructions)
                .MatchForward(false, // false = move at the start of the match, true = move at the end of the match
                    new CodeMatch(OpCodes.Stfld,typeof(UI_Make).GetField("_makeTime",(BindingFlags)(-1)))
                ).Repeat( matcher => // Do the following for each match
                    matcher
                    .InsertAndAdvance(
                        new CodeInstruction(OpCodes.Pop),
                        new CodeInstruction(OpCodes.Ldc_I4_0)
//                        new CodeInstruction(OpCodes.Ldc_I4_1),
//                        new CodeInstruction(OpCodes.Call,typeof(Math).GetMethod("Min",new Type[]{typeof(short),typeof(short)}))
                    ).Advance(1)
                ).InstructionEnumeration();
            return instructions;
        }
    }
    public static class TraitCost{
        static IEnumerable<MethodBase> TargetMethods(){
            yield return typeof(UI_NewGame).GetMethod("OnAbilityClick",(BindingFlags)(-1));
            yield return typeof(UI_NewGame).GetMethod("OnCellItemRender",(BindingFlags)(-1));
            yield return typeof(UI_NewGame).GetMethod("UpdatePoints",(BindingFlags)(-1));
            yield return typeof(UI_NewGame).GetMethod("OnStartNewGame",(BindingFlags)(-1));
        }
        public static IEnumerable<CodeInstruction> Transpiler(MethodBase __originalMethod, IEnumerable<CodeInstruction> instructions) {
            instructions = new CodeMatcher(instructions)
                .MatchForward(false, // false = move at the start of the match, true = move at the end of the match
                    new CodeMatch(OpCodes.Ldfld,typeof(Config.ProtagonistFeatureItem).GetField("Cost"))
                ).Repeat( matcher => // Do the following for each match
                    matcher
                    .InsertAndAdvance(
                        new CodeInstruction(OpCodes.Pop)
                    )
                    .SetAndAdvance(
                        OpCodes.Ldc_I4_0,null
                    )
                ).InstructionEnumeration();
            instructions = new CodeMatcher(instructions)
                .MatchForward(false, // false = move at the start of the match, true = move at the end of the match
                    new CodeMatch(OpCodes.Ldfld,typeof(Config.ProtagonistFeatureItem).GetField("PrerequisiteCost"))
                ).Repeat( matcher => // Do the following for each match
                    matcher
                    .InsertAndAdvance(
                        new CodeInstruction(OpCodes.Pop)
                    )
                    .SetAndAdvance(
                        OpCodes.Ldc_I4_0,null
                    )
                ).InstructionEnumeration();
            return instructions;
        }
    }
    [HarmonyPatch(typeof(CommonUtils),"GetCharacterHealthInfo")]
    public static class RevealHealth{
        public static void Postfix(ref ValueTuple<string, float> __result, short health, short leftHealth){
            if(N17==1){
                __result.Item1+="<color=#aec9e3>\n("+health.ToString()+"/"+leftHealth.ToString()+")</color>";
            }else if(N17==0){
                __result.Item1+="<color=#aec9e3>("+health.ToString()+"/"+leftHealth.ToString()+")</color>";
            }else {
                __result.Item1=health.ToString()+"<color=#aec9e3>/"+leftHealth.ToString()+"</color>";
            }
        }
    }
    [HarmonyPatch(typeof(UI_Combat),"OnInit")]
    public static class AutoFast {
        public static void Postfix(ref bool ____autoCombat, UI_Combat __instance, float ____displayTimeScale){
            ____autoCombat=true;
            ____displayTimeScale=2f; // 或许有效或许无效但我不准备管了。
            //GameData.GameDataBridge.GameDataBridge.AddMethodCall<float>(__instance.Element.GameDataListenerId, 8, 39, 5f);
            //typeof(UI_Combat).GetMethod("SetDisplayTimeScale",(BindingFlags)(-1)).Invoke(__instance,new object[]{2f});
            //__result.Item1+="<color=#aec9e3>\n("+health.ToString()+"/"+leftHealth.ToString()+"</color>)";
        }
    }
    [HarmonyPatch(typeof(UI_BuildingArea),"CanBuildAnywhere")]
    public static class UnlockShow {
        public static bool Postfix(bool result){
            return true;
        }
    }
    [HarmonyPatch(typeof(UI_CricketCombat),"SetEnemyCricketsVisible")]
    public static class Showququ{
        public static void Prefix(ref bool visible) {
            visible=true;
        }
    }
    [HarmonyPatch]
    public static class FastCricketDeploy {
        public static GameData.Domains.Item.ItemKey[] keys=new GameData.Domains.Item.ItemKey[]{GameData.Domains.Item.ItemKey.Invalid,GameData.Domains.Item.ItemKey.Invalid,GameData.Domains.Item.ItemKey.Invalid};
        public static MethodInfo OnClickSelectCricket=typeof(UI_CricketCombat).GetMethod("OnClickSelectCricket",(BindingFlags)(-1));
        [HarmonyPrefix]
        [HarmonyPatch(typeof(UI_CricketCombat),"StartBattleRound")]
        public static void Prfx(ref GameData.Domains.Item.ItemKey[] ____selfCricketKeys) {
            keys=____selfCricketKeys;
        }
        [HarmonyPostfix]
        [HarmonyPatch(typeof(UI_CricketCombat),"UpdateCurrWagerValue")]
        public static void Pstfx(UI_CricketCombat __instance, ref GameData.Domains.Item.ItemKey[] ____selfCricketKeys) {
            for(var index=0;index<3;index++)if(keys[index].IsValid())OnClickSelectCricket.Invoke(__instance,new object[]{keys[index]});
        }
    }
    [HarmonyPatch(typeof(WorldMapModel),"GetFullBlockName")]
    public static class WorldMapModelGetFullBlockName{
        public static string Postfix(string result, GameData.Domains.Map.FullBlockName fullBlockName) {
            if(fullBlockName.BlockData!=null){
                var blockPos = fullBlockName.BlockData.GetBlockPos();
                return result+"("+blockPos.X+","+blockPos.Y+")";
            } else {
                return result;
            }
        }
    }
    public static class UI_ShopUnlock{
        [HarmonyPatch(typeof(UI_Shop),"IsPageDisabled")]
        public static void Postfix(ref GameData.Domains.Merchant.OpenShopEventArguments ____openShopEventArguments) {
            ____openShopEventArguments.IgnoreWorldProgress=true;
            ____openShopEventArguments.IgnoreFavorability=true;
        }
    }
//    [HarmonyPatch(typeof(UI_CharacterMenuCombatSkill),"UpdateCurrPracticeSkillData")]
//    public static class Printing {
//        public static void Prefix(short ____currPracticeSelectedSkillId, CToggleGroup ____outlinePageTogGroup, CToggleGroup ____otherPageTogGroup){
//            if(____outlinePageTogGroup.GetActive().Key<0)return;
//            short state=1<<____outlinePageTogGroup.GetActive().Key;
//            for (int b = 5; b < 15; b ++) {
//                if(____otherPageTogGroup.Get(b).isOn)state|=1<<b;
//            }
//        }
//    }
    public static class UI_LegendaryBookOnNotifyGameData {
        [HarmonyTranspiler, HarmonyPatch(typeof(UI_LegendaryBook),"OnNotifyGameData")]
        public static IEnumerable<CodeInstruction> HTranspiler(MethodBase __originalMethod, IEnumerable<CodeInstruction> instructions) {
            instructions = new CodeMatcher(instructions)
                .MatchForward(false, // false = move at the start of the match, true = move at the end of the match
// 218	021C	ldarg.0
// 219	021D	ldfld	int32[] UI_LegendaryBook::_bookOwners
// 220	0222	ldloc.s	skillType (17)
// 221	0224	ldelem.i4
// 222	0225	ldarg.0
// 223	0226	ldfld	int32 UI_LegendaryBook::_taiwuCharId
// 224	022B	ceq
// 225	022D	stloc.s	canUse (18)
                    new CodeMatch(OpCodes.Ldarg_0),
                    new CodeMatch(OpCodes.Ldfld,typeof(UI_LegendaryBook).GetField("_bookOwners",(BindingFlags)(-1))),
                    new CodeMatch(i=>i.opcode==OpCodes.Ldloc_S),
                    new CodeMatch(OpCodes.Ldelem_I4),
                    new CodeMatch(OpCodes.Ldarg_0),
                    new CodeMatch(OpCodes.Ldfld,typeof(UI_LegendaryBook).GetField("_taiwuCharId",(BindingFlags)(-1))),
                    new CodeMatch(OpCodes.Ceq)
                ).Repeat( matcher => // Do the following for each match
                    matcher
                    .Advance(1)
                    .SetAndAdvance(
                        OpCodes.Ldfld,typeof(UI_LegendaryBook).GetField("_taiwuCharId",(BindingFlags)(-1))
                    ).SetAndAdvance(
                        OpCodes.Nop,null
                    ).SetAndAdvance(
                        OpCodes.Nop,null
                    )
                ).InstructionEnumeration();
            return instructions;
        }
        public static byte LegendaryBook=(byte)typeof(GameData.Domains.World.WorldFunctionType).GetField("LegendaryBook",(BindingFlags)(-1)).GetValue(null);
        [HarmonyPrefix,HarmonyPatch(typeof(UI_ResourceBar),"OnGameFunctionLockStateChange")]
        public static bool HPrefix(UI_ResourceBar __instance, FrameWork.ArgumentBox argBox) {
            byte functionId;
            if(argBox.Get("FunctionId", out functionId) && functionId == LegendaryBook){
                __instance.CGet<UnityEngine.GameObject>("LegendaryBook").SetActive(true);
                return false;
            } else {
                return true;
            }
        }
        [HarmonyPostfix,HarmonyPatch(typeof(UI_ResourceBar),"OnGameFunctionLockStateChange")]
        public static void HPostfix(UI_ResourceBar __instance, FrameWork.ArgumentBox argBox) {
            __instance.CGet<UnityEngine.GameObject>("LegendaryBook").SetActive(true);
        }
        [HarmonyPostfix,HarmonyPatch(typeof(UI_ResourceBar),"SetButtonForceInteractable")]
        public static void hPostfix(UI_ResourceBar __instance) {
            UIElement.ResourceBar.UiBaseAs<UI_ResourceBar>().CGet<UnityEngine.GameObject>("LegendaryBook").SetActive(true);
        }
        [HarmonyPostfix,HarmonyPatch(typeof(UI_ResourceBar),"OnInit")]
        public static void hpostfix(UI_ResourceBar __instance) {
            __instance.CGet<UnityEngine.GameObject>("LegendaryBook").SetActive(true);
        }
    }
    [HarmonyPatch(typeof(UI_Profession),"OnClick")]
    public static class Master0 {
        public static IEnumerable<CodeInstruction> Transpiler(MethodBase __originalMethod, IEnumerable<CodeInstruction> instructions) {
            return instructions.MethodReplacer(typeof(UI_Profession).GetMethod("OnClickSwitchProfession",(BindingFlags)(-1)), typeof(UI_Profession).GetMethod("ConfirmSwitchProfession",(BindingFlags)(-1)));
        }
    }
//     public static class UI_SelectSkillOnClick{
//         static IEnumerable<MethodBase> TargetMethods(){
//             foreach(var m in typeof(UI_SelectSkill).GetMethods((BindingFlags)(-1))){
//                 if(m.Name.Contains("<OnClick>")) {
//                     yield return m;
//                 }
//             }
//         }
//         public static IEnumerable<CodeInstruction> HTranspiler(MethodBase __originalMethod, IEnumerable<CodeInstruction> instructions) {
//             instructions = new CodeMatcher(instructions)
//                 .MatchForward(false, // false = move at the start of the match, true = move at the end of the match
// // 32	0052	callvirt	instance void UIManager::HideUI(class UIElement)
//                     new CodeMatch(OpCodes.Callvirt,typeof(UIManager).GetMethod("HideUI"), new Type[]{typeof(UIElement)})
//                 ).Repeat( matcher => // Do the following for each match
//                     matcher
//                     .InsertAndAdvance(
//                         new CodeInstruction(OpCodes.Ldloc_0),
//                         new CodeInstruction(OpCodes.Ldfld,typeof(UI_SelectSkill).GetField("_unselectableLifeSkillList",(BindingFlags)(-1)))
//                     ).SetAndAdvance(
//                         OpCodes.Call,typeof(UI_SelectSkillOnClick).GetMethod("HideUI")
//                     )
//                 ).InstructionEnumeration();
//             return instructions;
//         }
//         public static void HideUI(UIManager that, UIElement elem, List<short> sklst){
//             that.HideUI(this.Element);
//             that.ShowUI(this.Element);
//         }
//     }
    [HarmonyPatch(typeof(UI_BuildingArea),"SetBlockCannotMove")]
    public static class MoveGrid {
        public static IEnumerable<CodeInstruction> Transpiler(MethodBase __originalMethod, IEnumerable<CodeInstruction> instructions) {
            instructions = new CodeMatcher(instructions)
                .MatchForward(false, // false = move at the start of the match, true = move at the end of the match
                    new CodeMatch(OpCodes.Stloc_S),
                    new CodeMatch(OpCodes.Ldloc_S),
                    new CodeMatch(OpCodes.Brfalse)
                ).Repeat( (matcher) => {// Do the following for each match
                    logger("MoveGrid set SetBlockCannotMove(should appear only once)");
                    matcher.Advance(1).SetAndAdvance(
                        OpCodes.Ldc_I4_0,null
                    ).Advance(1); // advance(1)结尾是美德
                }).InstructionEnumeration();
            return instructions;
        }
    }
}
